package com.modernyuanshiren;

import java.time.Duration;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Game {
	private List<String> colors;
	private int numOfResultDigits;
	private final List<Guess> allGuesses;
	private static final String OUTPUT_FORMAT = "%d.%s\n";

	public Game(int numOfResultDigits, String elements) {
		this(numOfResultDigits, elements.split(""));
	}
	
	public Game(int numOfResultDigits, String... elements) {
		this.colors = Arrays.asList(elements);
		this.numOfResultDigits = numOfResultDigits;
		PermCombinationSupplier supplier = new PermCombinationSupplier(
				elements.length, numOfResultDigits);
		supplier.setDisplayMapper(this.colors::get);
		allGuesses = new ArrayList<>();
		try {
			Stream.generate(supplier).map(Guess::new)
					.forEach(allGuesses::add);
		} catch (Exception e) {
		}
	}

	public void resolve() {
		int i = 1;
		boolean isEnd = false;
		Random r = new Random();
		int answerIdx = r.nextInt(allGuesses.size());
		List<Guess> range = allGuesses.stream().collect(Collectors.toList());
		try(Scanner sc = new Scanner(System.in)) {
			while (!isEnd) {
				Guess selectedGuess = outputGuess(i, range, answerIdx);
				Result result = inputAB(sc);
				if (numOfResultDigits > 5 && i == 1) {
					System.out.println("Calculating,please wait......");
				}
				Record selectedRecord = new Record(selectedGuess, result);
				isEnd = selectedRecord.isEnd();
				if (!isEnd) {
					range.remove(answerIdx);
					List<Guess> temp = range.parallelStream()
							.filter(g -> g.match(selectedRecord))
							.collect(Collectors.toList());
					LocalTime start = LocalTime.now();
					answerIdx = IntStream
							.range(0, temp.size())
							.boxed()
							.max(Comparator.comparingDouble(g -> InfoUtil.getInfo(
									temp.get(g), temp))).get();
					if (numOfResultDigits > 5 && i == 1) {
						Long dur = Duration.between(start, LocalTime.now()).getSeconds();
						System.out.println(dur +"s");
					}
					range = temp.stream().collect(Collectors.toList());
					i++;
				} else {
					System.out.println("Success!");
				}
			}
		}
	}

	private Result inputAB(Scanner sc) {
		System.out.print("please input number of A:");
		int a = sc.nextInt();
		System.out.print("please input number of B:");
		int b = sc.nextInt();
		System.out.printf("%dA%dB\n", a, b);
		Result result = new Result(a, b);
		return result;
	}

	private Guess outputGuess(int i, List<Guess> range, int answerIdx) {
		Guess selectedGuess = range.get(answerIdx);
		System.out.printf(OUTPUT_FORMAT, i, selectedGuess.getAnswer());
		return selectedGuess;
	}

	public static void main(String[] args) {
		Game game = new Game(6, "灰黄橙粉赤紫青緑");
//		Game game = new Game(4, "0123456789");
		game.resolve();
	}
}
